/*
 * @Author: xuetao 3168581151@qq.com
 * @Date: 2025-01-04
 * @LastEditors: xuetao 3168581151@qq.com
 * @LastEditTime: 2025-02-08
 * @Description: 单例模式，网络请求
 */
import 'package:dio/dio.dart';
import 'package:logger/logger.dart';
import 'package:chat_client/repositories/auth_repository.dart';

import 'package:chat_client/config/api_config.dart';

class ApiService {
  // 1. 声明一个静态私有实例
  static final ApiService _instance = ApiService._internal();

  // 2. getter
  static ApiService get instance => _instance;

  // 3. 私有构造函数
  ApiService._internal() {
    _dio.interceptors.add(InterceptorsWrapper(
      /**
       * 请求拦截
       */
      onRequest: (options, handler) async {
        if (options.uri.path == '/user/login' ||
            options.uri.path == '/user/register') {
          return handler.next(options); // 不需要添加 token，直接放行
        }
        // 获取本地存储的 token
        final token = AuthRepository.token;

        if (token != null) {
          // options.headers['Authorization'] = 'Bearer $token';
          options.headers['Authorization'] = token;
        }

        logger.i("Request: ${options.method} ${options.uri}"); // 打印请求信息
        return handler.next(options);
      },
      /**
       * 响应拦截器
       */
      onResponse: (response, handler) {
        return handler.next(response);
      },
      /**
       * 错误拦截
       */
      onError: (DioException err, handler) {
        if (err.response != null && err.response!.data != null) {
          final statusCode = err.response?.statusCode;
          final message = err.response!.data['message'] ?? '未知错误';
          final requestUrl = err.requestOptions.uri.toString();
          final method = err.requestOptions.method;

          final customError = DioException(
            requestOptions: err.requestOptions,
            response: err.response,
            error: message,
          );

          logger.e(
              'Error $statusCode: $message, Method: $method, URL: $requestUrl');
          return handler.next(customError);
        } else {
          logger.e(err);
          return handler.next(err);
        }
      },
    ));
  }

  var logger = Logger();

  // 4. 私有 Dio 实例
  final Dio _dio = Dio(BaseOptions(
    baseUrl: baseUrl,
    connectTimeout: const Duration(milliseconds: 5000),
    receiveTimeout: const Duration(milliseconds: 3000),
  ));

  // GET 请求，带查询参数
  Future<dynamic> get(String url, {Map<String, dynamic>? params}) async {
    return _request(() => _dio.get(url, queryParameters: params));
  }

  // POST 请求
  Future<dynamic> post(String url, Map<String, dynamic> data) async {
    return _request(() => _dio.post(url, data: data));
  }

  // PUT 请求
  Future<dynamic> put(String url, Map<String, dynamic> data) async {
    return _request(() => _dio.put(url, data: data));
  }

  // DELETE 请求
  Future<dynamic> delete(String url, {Map<String, dynamic>? data}) async {
    return _request(() => _dio.delete(url, data: data));
  }

  // 统一的请求处理方法
  Future<Map<String, dynamic>> _request(
      Future<Response> Function() request) async {
    try {
      final response = await request();
      print('检查响应：$response');
      return response.data;
    } catch (e) {
      if (e is DioException) {
        throw ApiError(message: e.error.toString());
      }
      rethrow;
    }
  }

  // FormData 上传
  Future<dynamic> postFormData(String url, FormData formData) async {
    return _request(() => _dio.post(url, data: formData));
  }

  // 文件下载
  Future<void> downloadFile(String url, String savePath) async {
    try {
      await _dio.download(
        url,
        savePath,
        onReceiveProgress: (received, total) {
          if (total != -1) {
            logger.i("${(received / total * 100).toStringAsFixed(0)}%");
          }
        },
      );
    } catch (e) {
      logger.e("Error in file download: $e");
      rethrow;
    }
  }
}

// 自定义错误类型，用于处理服务端返回的响应体错误
class ApiError implements Exception {
  final String message;

  ApiError({required this.message});

  @override
  String toString() {
    return message;
  }
}
